﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using SoonCode.Core;

namespace SoonCode.FocusTest.Utils
{
    class SoundPlayer
    {
        private List<string> playList;
        private int playIndex = 0;
        private CancellationTokenSource cts;
        private CancellationToken taskToken;
        private static SoundPlayer instance;
        private MediaPlayer player;
        private MediaPlayer asyncPlayer;
        private double speed = 1;
        private static MediaPlayer Player
        {
            get
            {
                return Instance.player;
            }
        }

        private SoundPlayer()
        {
            playList = new List<string>();
            player = new MediaPlayer();
            asyncPlayer=new MediaPlayer();
            player.MediaOpened += Player_MediaOpened;
            player.MediaFailed += Player_MediaFailed;
            cts = new CancellationTokenSource();
            taskToken = cts.Token;
        }

        private void Player_MediaFailed(object? sender, ExceptionEventArgs e)
        {
            Console.WriteLine(e);
        }

        private void Player_MediaOpened(object? sender, EventArgs e)
        {
            player.SpeedRatio = speed;
            player.Play();
            if (player.SpeedRatio != 1)
            {
                Thread.Sleep(100);
                player.Position = TimeSpan.MinValue;
                // player.Play();
            }
        }

        private void StopTask()
        {

            if (taskToken.CanBeCanceled)
            {
                cts.Cancel();
                cts = new CancellationTokenSource();
                taskToken = cts.Token;
            }
        }

        public static void Stop()
        {
            Instance.playList.Clear();
            Instance.StopTask();
            Player.Dispatcher.Invoke(() =>
            {
                Player.Stop();
            });

        }

        public static void Open(string path)
        {
            Player.Dispatcher.Invoke(() =>
            {
                if (Player.Source != null && Player.Source.ToString() == path)
                {
                    Thread.Sleep(100);
                    Player.Position = TimeSpan.MinValue;
                    Player.Play();
                }

                else
                    Player.Open(new Uri(path, UriKind.RelativeOrAbsolute));

            });
        }
        public static SoundPlayer Instance
        {
            get
            {
                if (instance == null)
                    instance = new SoundPlayer();
                return instance;
            }
        }
        public async static void PlayDing()
        {
            await Task.Delay(400);
            Stop();
            Open(@"./Sound/ding.wav");
        }
        public static void PlayButton()
        {
            string path = @"./Sound/button.mp3";
            Instance.asyncPlayer.Open(new Uri(path, UriKind.RelativeOrAbsolute));
            Instance.asyncPlayer.Play();
        }


        public static void Play(string name, double speed = 1, Action callback=null)
        {
            Stop();
            Instance.speed = speed;
            Task.Run(async () =>
            {
                string[] names = name.Split(":");
                if(names.Length >1)
                {
                    await Task.Delay(names[0].ToInt());
                    name=names[1];
                }

                Open($"./Sound/{name}");
            }, Instance.taskToken);
        }



        public static void PlayStrings(string[] str, Action callback)
        {
            Stop();
            Instance.speed = 1;
            foreach (var s in str)
            {
                string[] split = s.Split(':');
                Instance.playList.Add(split[0] + ".mp3" + (split.Length > 1 ? ":" + split[1] : ""));
            }
            Task.Run(() =>
            {
                try
                {
                    foreach (var name in Instance.playList)
                    {
                        if (Instance.taskToken.IsCancellationRequested) break;
                        string[] split = name.Split(":");
                        if (Instance.taskToken.IsCancellationRequested) break;
                        Open($"./Sound/{split[0]}");
                        if (Instance.taskToken.IsCancellationRequested) break;
                        if (split.Length > 1)
                            Thread.Sleep(split[1].ToInt());
                        if (Instance.taskToken.IsCancellationRequested) break;
                    }

                    if (!Instance.taskToken.IsCancellationRequested && callback != null)
                    {
                        callback();
                    }
                }
                catch
                {
                }
            }, Instance.taskToken);
        }
        public static void PlayNumberString(string number, Action callback)
        {
            Stop();
            foreach (var c in number)
            {
                Instance.playList.Add(c + ".mp3");
            }
            Task.Run(() =>
            {
                try
                {
                    foreach (var name in Instance.playList)
                    {
                        Thread.Sleep(1000);
                        if (Instance.taskToken.IsCancellationRequested)
                        {
                            Console.WriteLine(number+"停止");
                            break;
                        }
                        Open($"./Sound/{name}");
                    }

                    if (!Instance.taskToken.IsCancellationRequested && callback != null)
                    {
                        callback();
                    }
                }
                catch
                {
                }
            }, Instance.taskToken);

        }

    }
}
